#ifndef JOB_H_
#define JOB_H_

#include "Data.h"
#define MIN_JOB_LEN 0 // minimal job length possible
#define INIT_JOB_ID 0 // used to initialize job counter and therefore first given job ID

// #define INIT_LAST_RUN_TIME -1 // initialize last run time with a negative number, since a job can be executed at 0 time // TODO DELETE

class Job: public Data {
protected:
	static unsigned int m_jobCounter; // counts jobs in system, used to initialize new job's ID
	const int m_jobID; // job's ID
	const unsigned int m_startTime; // job's start time
	const int m_priority; // job's priority
	unsigned int m_length; // amount of time-units required to perform task


	//int m_lastRunTime; // time-stamp of last time job was executed // TODO DELETE

	/***************************************************************************************
	* function name: Job(const Job& jobToCopy)
	* The Input: Job to be copied
	* The output: None
	* The Function operation: Creates a new job with the same attributes as given job's
	***************************************************************************************/
	Job(const Job& jobToCopy);

public:
	/***************************************************************************************
	* function name: Job(const unsigned int startTime, const unsigned int length, const int priority)
	* The Input: Values for new job's attributes
	* The output: None
	* The Function operation: Creates a new job with given attributes
	***************************************************************************************/
	Job(const unsigned int startTime, const unsigned int length, const int priority);

	/***************************************************************************************
	* function name: ~Job()
	* The Input: None
	* The output: None
	* The Function operation: Destructs Job object
	***************************************************************************************/
	virtual ~Job() = 0; // TODO DEBUG!!! // MIGHT NOT BE PURE VIRTUAL

	/***************************************************************************************
	* function name: virtual void work()
	* The Input: None
	* The output: None
	* The Function operation: Performs job's task for a single time unit
	***************************************************************************************/
	//void work(const int systemTime, const int type); // TODO DEBUG!!!
	virtual void work(const int systemTime, const int type);

	/***************************************************************************************
	* function name: bool isImprotant(const Job& otherJob) const
	* The Input: Reference to job to be compared with
	* The output: True if activating object's priority is higher than given job's, else False
	* The Function operation: Compares jobs' priority attribute and returns comparison's
	* 				          result. Method does not change the object
	***************************************************************************************/
	bool isImprotant(const Job& otherJob) const {return m_priority > otherJob.m_priority;}

	/***************************************************************************************
	* function name: bool isPriorityEqual(const Job& otherJob) const
	* The Input: Reference to job to be compared with
	* The output: True if activating object's priority is equal to given job's, else False
	* The Function operation: Compares jobs' priority attribute and returns comparison's
	* 				          result. Method does not change the object
	***************************************************************************************/
	bool isPriorityEqual(const Job& otherJob) const {return m_priority == otherJob.m_priority;}

	/***************************************************************************************
	* function name: bool isEarly(const Job& otherJob) const
	* The Input: Reference to job to be compared with
	* The output: True if activating object's start time is lower than given job's, else False
	* The Function operation: Compares jobs' start time attribute and returns comparison's
	* 				          result. Method does not change the object
	***************************************************************************************/
	bool isEarly(const Job& otherJob) const {return m_startTime < otherJob.m_startTime;}

	/***************************************************************************************
	* function name: bool isEarly(const unsigned int systemTime) const
	* The Input: System time
	* The output: True if activating object's start time is lower than given time, else False
	* The Function operation: Compares job's start time to given time and returns comparison's
	* 				          result. Method does not change the object
	***************************************************************************************/
	bool isEarly(const unsigned int systemTime) const {return m_startTime < systemTime;} // TODO CHECK IF CAN BE DELETED

	/***************************************************************************************
	* function name: bool readyToRun(const unsigned int systemTime) const
	* The Input: System time
	* The output: True if activating object's start time is lower or equal than given time,
	* 			  else False
	* The Function operation: Compares job's start time to given time and returns comparison's
	* 				          result. Method does not change the object
	***************************************************************************************/
	bool readyToRun(const unsigned int systemTime) const {return m_startTime <= systemTime;} // TODO might be deleted

	/***************************************************************************************
	* function name: bool isStartTimeEqual(const Job& otherJob) const
	* The Input: Reference to job to be compared with
	* The output: True if activating object's start time is equal to given job's, else False
	* The Function operation: Compares jobs' start time attribute and returns comparison's
	* 				          result. Method does not change the object
	***************************************************************************************/
	bool isStartTimeEqual(const Job& otherJob) const {return m_startTime == otherJob.m_startTime;}

	/***************************************************************************************
	* function name: bool isStartTimeEqual(const int systemTime) const
	* The Input: System time
	* The output: True if activating object's start time is equal to given time, else False
	* The Function operation: Compares job's start time to given time and returns comparison's
	* 				          result. Method does not change the object
	***************************************************************************************/
	bool isStartTimeEqual(const unsigned int systemTime) const {return m_startTime == systemTime;}

	/***************************************************************************************
	* function name: bool executedEarlier(const Job& otherJob) const
	* The Input: Reference to job to be compared with
	* The output: True if activating object's last run time is earlier than given job's, else False
	* The Function operation: Compares jobs' last run time attribute and returns comparison's
	* 				          result. Method does not change the object
	***************************************************************************************/
	//bool executedEarlier(const Job& otherJob) const {return m_lastRunTime  < otherJob.m_lastRunTime;} // TODO DELETE

	/***************************************************************************************
	* function name: bool executeSameTime(const Job& otherJob) const
	* The Input: Reference to job to be compared with
	* The output: True if both jobs' last run time is equal
	* The Function operation: Compares jobs' last run time attribute and returns comparison's
	* 				          result. Method does not change the object
	***************************************************************************************/
	//bool executeSameTime(const Job& otherJob) const {return m_lastRunTime  == otherJob.m_lastRunTime;} // TODO might be deleted

	/***************************************************************************************
	* function name: bool isNewer(const Job& otherJob) const
	* The Input: Reference to job to be compared with
	* The output: True if activating object's ID is smaller than given job's, else False
	* The Function operation: Compares jobs' ID attribute and returns comparison's
	* 				          result. ID attribute is compared because the earlier a job is
	* 				          created, the smaller its ID is.
	* 				          Method does not change the object
	***************************************************************************************/
	bool isNewer(const Job& otherJob) const {return m_jobID < otherJob.m_jobID;}

	/***************************************************************************************
	* function name: bool isJobDone() const
	* The Input: None
	* The output: True if object's length attribute is greater than minimal job length, else False
	* The Function operation: Compares jobs' length attribute to minimal job length and returns
	* 						  comparison's result. Method does not change the object
	***************************************************************************************/
	bool isJobDone() const {return m_length > MIN_JOB_LEN;}
};

#endif
